# ------------------
# Techniques de développement
# M1 ALMA 2011-2012
# Pauline Folz - Adrien Quillet
# 
#
# ------------------
# Documentation
# ------------------
#
# CHECK_QT
# --------
#
# Invoquer CHECK_QT effectue les actions suivantes :
#	- Trouve les programmes suivants, et les stockent dans les variables
#	  suivantes :
#		- qmake : $(QMAKE)
#		- moc   : $(MOC)
#		- uic   : $(UIC)
#		- rcc   : $(RCC)
#	- Stockage des flags pour utiliser Qt :
#		- $(QT_DEFINES)  : -D définis par qmake
#		- $(QT_CFLAGS)   : CFLAGS définis par qmake
#		- $(QT_CXXFLAGS) : CXXFLAGS définis par qmake
#		- $(QT_INCPATH)  : Include définis par qmake
#		- $(QT_LDFLAGS)  : Lib. Path définis par qmake
#		- $(QT_LIBS)     : LIBS définis par qmake
#	  Ces flags sont définis en parsant un Makefile généré par qmake. Il peut
#	  être nécessaire de les compléter si vous utilisez des composants spéciaux
#	  de Qt, comme QtXML.
#	- Défini l'option --with-qt-dir=/qt/dir
#		La fonction ira chercher les binaires et bibliothèques de Qt dans ce
#		répertoire en priorité
#	- Défini l'option --with-tmpdir-name=dirname
#		Nom du répertoire à créer pour faire les tests Qt. Par défaut : tmp_qt_test
#

AC_DEFUN([CHECK_QT],
[

AC_REQUIRE([AC_PROG_CC])
AC_REQUIRE([AC_PROG_CXX])
AC_REQUIRE([AC_PROG_SED])
AC_REQUIRE([AC_PROG_GREP])

AC_PATH_PROG([SORT], [sort], [not-found], [$PATH])
if test "$SORT" = not-found ; then
	AC_MSG_ERROR([Cannot find sort.])
fi
AC_PATH_PROG([TR], [tr], [not-found], [$PATH])
if test "$TR" = not-found ; then
	AC_MSG_ERROR([Cannot find tr.])
fi
AC_PATH_PROG([XARGS], [xargs], [not-found], [$PATH])
if test "$XARGS" = not-found ; then
	AC_MSG_ERROR([Cannot find xargs.])
fi

AC_ARG_WITH([qt-dir], 
			[AS_HELP_STRING([--with-qt-dir],
							[Qt directory, like /usr/local/Trolltech])],
			[qt_dir=$with_qt_dir],
			[qt_dir=""])
			
AC_ARG_WITH([qt-tmpdir-name], 
			[AS_HELP_STRING([--with-qt-tmpdir-name],
							[Where to work ; default = tmp_qt_test])],
			[qt_tmpdir_name=$with_qt_tmpdir_name],
			[qt_tmpdir_name="tmp_qt_test"])

if ! test "$qt_dir" = "" ; then
	# Recherche des binaires de Qt dans qt_dir
	AC_MSG_CHECKING([for Qt in $qt_dir])
	if test -d "$qt_dir" ; then
		dnl On prend toutes les version de Qt, on enleve les retour a la ligne, on les tri suivant
		dnl le numero des version decroissant, on retire les espaces en trop avec xargs et on separe chaque
		dnl version par des : .
		QT_PATHS=`echo "$qt_dir"/*/bin | tr ' ' '\n' | sort -nr | xargs | sed 's/  */:/g'`
		AC_MSG_RESULT([found])
	else
		AC_MSG_RESULT([not found])
	fi
fi

# Recherche de qmake
AC_PATH_PROG([QMAKE], [qmake], [not-found], [$QT_PATHS:$PATH])
if test "$QMAKE" = not-found ; then
	AC_MSG_ERROR([Cannot find qmake.])
fi

# Recherche de moc
AC_PATH_PROG([MOC], [moc], [not-found], [$QT_PATHS:$PATH])
if test "$MOC" = not-found ; then
	AC_MSG_ERROR([Cannot find moc.])
fi

# Recherche de uic
AC_PATH_PROG([UIC], [uic], [not-found], [$QT_PATHS:$PATH])
if test "$UIC" = not-found ; then
	AC_MSG_ERROR([Cannot find uic.])
fi

# Recherche de rcc
AC_PATH_PROG([RCC], [rcc], [not-found], [$QT_PATHS:$PATH])
if test "$RCC" = not-found ; then
	AC_MSG_ERROR([Cannot find rcc.])
fi

# Il faut tester si Qt fonctionne correctement. On va donc créer des sources
# et les compiler.

# On créer un repertoire temporaire pour travailler.
AC_MSG_NOTICE([Creating $tmpdir_name])

if ! test -d "$qt_tmpdir_name" ; then
	mkdir "$qt_tmpdir_name"
	if ! test -w "$qt_tmpdir_name"  ; then
		AC_MSG_ERROR([can not write into directory $qt_tmpdir_name])
	fi
fi

AC_MSG_NOTICE([Moving into $tmpdir_name])
cd "$qt_tmpdir_name"

AC_MSG_NOTICE([Creating conftest.h])
cat > conftest.h << EOF
#include <QObject>

class FouBarre : public QObject {
	Q_OBJECT
public:
	FouBarre();
	~FouBarre() {}
public slots:
	void setValue(int value);
signals:
	void valueChanged(int value);
private:
	int _value;
};
EOF

AC_MSG_NOTICE([Creating conftest.cpp])
cat > conftest.cpp << EOF
#include "conftest.h"

FouBarre::FouBarre() :
	_value(42)
{
	connect(this, SIGNAL(valueChanged(int)), this, SLOT(setValue(int)));
}

void FouBarre::setValue(int value)
{
	_value = value;
}

int main()
{
	FouBarre f;
	return 0 ;
}
EOF

AC_MSG_NOTICE([Invoking qmake -project])
if ! $QMAKE -project ; then
	AC_MSG_ERROR([Fail to invoke qmake -projectl])
fi

AC_MSG_NOTICE([Invoking qmake])
if ! $QMAKE ; then
	AC_MSG_ERROR([Fail to invoke qmake])
fi

AC_MSG_CHECKING([Qt flags])

QT_DEFINES=`cat Makefile | grep ^DEFINES | sed 's/^DEFINES *= //g' | sed 's/$(SUBLIBS)//g' | sed 's/$(DEFINES)/$(QT_DEFINES)/g'`
QT_CFLAGS=`cat Makefile | grep ^CFLAGS | sed 's/^CFLAGS *= //g' | sed 's/$(SUBLIBS)//g' | sed 's/$(DEFINES)/$(QT_DEFINES)/g'`
QT_CXXFLAGS=`cat Makefile | grep ^CXXFLAGS | sed 's/^CXXFLAGS *= //g' | sed 's/$(SUBLIBS)//g' | sed 's/$(DEFINES)/$(QT_DEFINES)/g'`
QT_INCPATH=`cat Makefile | grep ^INCPATH | sed 's/^INCPATH *= //g' | sed 's/$(SUBLIBS)//g' | sed 's/$(DEFINES)/$(QT_DEFINES)/g'`
QT_LDFLAGS=`cat Makefile | grep ^LFLAGS | sed 's/^LFLAGS *= //g' | sed 's/$(SUBLIBS)//g' | sed 's/$(DEFINES)/$(QT_DEFINES)/g'`
QT_LIBS=`cat Makefile | grep ^LIBS | sed 's/^LIBS *= //g' | sed 's/$(SUBLIBS)//g' | sed 's/$(DEFINES)/$(QT_DEFINES)/g'`

dnl Pour faire les tests de compilation
QT_DEFINES_tmp=`cat Makefile | grep ^DEFINES | sed 's/^DEFINES *= //g' | sed 's/$(SUBLIBS)//g' | sed 's/$(DEFINES)//g'`
QT_CFLAGS_tmp=`cat Makefile | grep ^CFLAGS | sed 's/^CFLAGS *= //g' | sed 's/$(SUBLIBS)//g' | sed 's/$(DEFINES)//g'`
QT_CXXFLAGS_tmp=`cat Makefile | grep ^CXXFLAGS | sed 's/^CXXFLAGS *= //g' | sed 's/$(SUBLIBS)//g' | sed 's/$(DEFINES)//g'`
QT_INCPATH_tmp=`cat Makefile | grep ^INCPATH | sed 's/^INCPATH *= //g' | sed 's/$(SUBLIBS)//g' | sed 's/$(DEFINES)//g'`
QT_LDFLAGS_tmp=`cat Makefile | grep ^LFLAGS | sed 's/^LFLAGS *= //g' | sed 's/$(SUBLIBS)//g' | sed 's/$(DEFINES)//g'`
QT_LIBS_tmp=`cat Makefile | grep ^LIBS | sed 's/^LIBS *= //g' | sed 's/$(SUBLIBS)//g' | sed 's/$(DEFINES)//g'`

AC_SUBST([QT_DEFINES])
AC_SUBST([QT_CFLAGS])
AC_SUBST([QT_CXXFLAGS])
AC_SUBST([QT_INCPATH])
AC_SUBST([QT_LDFLAGS])
AC_SUBST([QT_LIBS])

AC_MSG_RESULT([done])

AC_MSG_CHECKING([if moc works])
AC_TRY_EVAL("$MOC conftest.h -o moc_conftest.cpp")
if test "$ac_status" != 0; then
   AC_MSG_ERROR([moc failed !])
fi
AC_MSG_RESULT([ok])

AC_MSG_CHECKING([if we can compile moc result])
AC_TRY_EVAL("$CXX -c $QT_CXXFLAGS_tmp $QT_DEFINES_tmp $QT_INCPATH_tmp -o moc_conftest.o moc_conftest.cpp")
if test "$ac_status" != 0; then
   AC_MSG_ERROR(can not compile moc result !)
fi
AC_MSG_RESULT([ok])

AC_MSG_CHECKING([if we can compile app sources])
AC_TRY_EVAL("$CXX $QT_INCPATH_tmp -c $QT_CXXFLAGS_tmp $QT_DEFINES_tmp -o conftest.o conftest.cpp")
if test "$ac_status" != 0; then
   AC_MSG_ERROR(can not compile app sources !)
fi
AC_MSG_RESULT([ok])

AC_MSG_CHECKING([if we can link app])
AC_TRY_EVAL("$CXX $QT_LDFLAGS_tmp -o conftest conftest.o moc_conftest.o $QT_LIBS_tmp")
if test "$ac_status" != 0 ; then
   AC_MSG_ERROR(can not link app !)
fi
if ! test -f conftest ; then
	AC_MSG_ERROR([can not link app !])
fi
AC_MSG_RESULT([ok])

AC_MSG_CHECKING([if we can launch app])
AC_TRY_EVAL("./conftest")
if test "$ac_status" != 0; then
   AC_MSG_ERROR(can not launch app !)
fi
AC_MSG_RESULT([ok])

AC_MSG_NOTICE([Moving into ..])
cd ..

AC_MSG_NOTICE([Deleting $tmpdir_name])
rm -rf "$qt_tmpdir_name"

AC_MSG_NOTICE([Cleaning tmp variables])
AS_UNSET([QT_DEFINES_tmp])
AS_UNSET([QT_CFLAGS_tmp])
AS_UNSET([QT_CXXFLAGS_tmp])
AS_UNSET([QT_INCPATH_tmp])
AS_UNSET([QT_LDFLAGS_tmp])
AS_UNSET([QT_LIBS_tmp])

])
